package at.fhv.androideightpuzzle.puzzles;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;

import at.fhv.androideightpuzzle.R;
import at.fhv.androideightpuzzle.domain.EightPuzzle;
import at.fhv.androideightpuzzle.domain.EmptyPart;
import at.fhv.androideightpuzzle.domain.PuzzleBoard;
import at.fhv.androideightpuzzle.domain.PuzzlePart;

public class PuzzleLoader {
	
	public static final String PUZZLES_FILE="puzzles.json";
	
	public static final String EMPTY_PART="emptypart";
	public static final String END_STATE="endstate";
	public static final String IMAGE="image";
	public static final String NUMBER="number";
	public static final String PARTS="parts";
	public static final String PUZZLES="puzzles";
	public static final String PUZZLE_ID="puzzleid";
	
	public static int[] loadImageIds(String puzzleId){
		if((puzzleId!=null) && (puzzleId.equals("")==false)){
			String content=loadContent();
			
			if((content!=null) && (content.equals("")==false)){
				try{
					JSONParser parser=new JSONParser();
					
					JSONArray jsonArr=(JSONArray)((JSONObject)parser.parse(content)).get(PuzzleLoader.PUZZLES);
					
					for(int i=0; i<jsonArr.size(); i++){
						JSONObject puzzle=(JSONObject)jsonArr.get(i);
						
						if((puzzle.get(PuzzleLoader.PUZZLE_ID)!=null) && (puzzle.get(PuzzleLoader.PUZZLE_ID).equals(puzzleId))){
							//found the puzzle
							JSONArray partsJsonArr=(JSONArray)puzzle.get(PuzzleLoader.PARTS);
							int[] ids=new int[(partsJsonArr.size()+1)];
							
							for(int j=0; j<partsJsonArr.size(); j++){
								String resName=(String)((JSONObject)partsJsonArr.get(j)).get(PuzzleLoader.IMAGE);
								ids[j]=R.drawable.class.getField(resName).getInt(null);
							}
							
							ids[(ids.length-1)]=R.drawable.class.getField("empty_part").getInt(null);
							
							return ids;
						}
					}
				}catch(IllegalAccessException exc){
					android.util.Log.e("PuzzleLoader",exc.getLocalizedMessage(),exc);
				}catch(ParseException exc){
					android.util.Log.e("PuzzleLoader",exc.getLocalizedMessage(),exc);
				}catch(NoSuchFieldException exc){
					android.util.Log.e("PuzzleLoader",exc.getLocalizedMessage(),exc);
				}
			}
			
			return null;
		}else{
			return null;
		}
	}
	
	public static int loadImageIdForPuzzle(String puzzleId){
		if((puzzleId!=null) && (puzzleId.equals("")==false)){
			String content=loadContent();
			
			if((content!=null) && (content.equals("")==false)){
				try{
					JSONParser parser=new JSONParser();
					
					JSONArray jsonArr=(JSONArray)((JSONObject)parser.parse(content)).get(PuzzleLoader.PUZZLES);
					
					for(int i=0; i<jsonArr.size(); i++){
						JSONObject puzzle=(JSONObject)jsonArr.get(i);
						
						if((puzzle.get(PuzzleLoader.PUZZLE_ID)!=null) && (puzzle.get(PuzzleLoader.PUZZLE_ID).equals(puzzleId))){
							//found the puzzle
							String resName=(String)puzzle.get(PuzzleLoader.IMAGE);
							
							return R.drawable.class.getField(resName).getInt(null);
						}
					}
				}catch(IllegalAccessException exc){
					android.util.Log.e("PuzzleLoader",exc.getLocalizedMessage(),exc);
				}catch(ParseException exc){
					android.util.Log.e("PuzzleLoader",exc.getLocalizedMessage(),exc);
				}catch(NoSuchFieldException exc){
					android.util.Log.e("PuzzleLoader",exc.getLocalizedMessage(),exc);
				}
			}
			
			return -1;
		}else{
			return -1;
		}
	}
	
	public static EightPuzzle loadPuzzleById(String puzzleId){
		if((puzzleId!=null) && (puzzleId.equals("")==false)){
			String content=loadContent();
			
			if((content!=null) && (content.equals("")==false)){
				try{
					JSONParser parser=new JSONParser();
					
					JSONArray jsonArr=(JSONArray)((JSONObject)parser.parse(content)).get(PuzzleLoader.PUZZLES);
					
					for(int i=0; i<jsonArr.size(); i++){
						JSONObject puzzle=(JSONObject)jsonArr.get(i);
						
						if((puzzle.get(PuzzleLoader.PUZZLE_ID)!=null) && (puzzle.get(PuzzleLoader.PUZZLE_ID).equals(puzzleId))){
							//found the puzzle
							JSONArray endStateJsonArr=(JSONArray)puzzle.get(PuzzleLoader.END_STATE);
							int[] endState=new int[endStateJsonArr.size()];
							
							for(int j=0; j<endState.length; j++){
								endState[j]=((Number)endStateJsonArr.get(j)).intValue();
							}
							
							JSONObject emptyPartJsonObj=(JSONObject)puzzle.get(PuzzleLoader.EMPTY_PART);
							EmptyPart emptyPart=new EmptyPart(((Number)emptyPartJsonObj.get(PuzzleLoader.NUMBER)).intValue());
							
							JSONArray partsJsonArr=(JSONArray)puzzle.get(PuzzleLoader.PARTS);
							PuzzlePart[] parts=new PuzzlePart[partsJsonArr.size()];
							
							for(int j=0; j<partsJsonArr.size(); j++){
								JSONObject partJsonObj=(JSONObject)partsJsonArr.get(j);
								parts[j]=new PuzzlePart(((Number)partJsonObj.get(PuzzleLoader.NUMBER)).intValue());
							}
							
							parts[(parts.length-1)]=emptyPart;
							
							//return a new eight puzzle
							return new EightPuzzle(puzzleId,new PuzzleBoard(parts,endState));
						}
					}
				}catch(ParseException exc){
					android.util.Log.e("PuzzleLoader",exc.getLocalizedMessage(),exc);
				}
			}
			
			return null;
		}else{
			return null;
		}
	}
	
	public static String[] loadPuzzleIds(){
		return loadPuzzleIdsAsList().toArray(new String[0]);
	}
	
	public static List<String> loadPuzzleIdsAsList(){
		List<String> puzzleIds=new ArrayList<String>();
		String content=loadContent();
		
		if((content!=null) && (content.equals("")==false)){
			try{
				JSONParser parser=new JSONParser();
				
				JSONArray jsonArr=(JSONArray)((JSONObject)parser.parse(content)).get(PuzzleLoader.PUZZLES);
				
				for(int i=0; i<jsonArr.size(); i++){
					puzzleIds.add((String)((JSONObject)jsonArr.get(i)).get(PuzzleLoader.PUZZLE_ID));
				}
			}catch(ParseException exc){
				android.util.Log.e("PuzzleLoader",exc.getLocalizedMessage(),exc);
			}
		}
		
		return puzzleIds;
	}
	
	private static String loadContent(){
		BufferedReader br=null;
		
		try{
			br=new BufferedReader(new InputStreamReader(PuzzleLoader.class.getResourceAsStream(PuzzleLoader.PUZZLES_FILE)));
			StringBuilder sb=new StringBuilder();
			String line=br.readLine();
			
			while(line!=null){
				sb.append(line);
				
				line=br.readLine();
			}
			
			return sb.toString();
		}catch(Exception exc){
			return null;
		}finally{
			try{
				br.close();
			}catch(Exception exc){
				android.util.Log.e("PuzzleLoader",exc.getLocalizedMessage(),exc);
			}
		}
	}
}
